package routers

import (
	"encoding/json"
	"errors"
	"fmt"
	"github.com/gin-gonic/gin"
	"io/ioutil"
	"net"
	"net/http"
	"strconv"
	"strings"
	"ztool/common"
	"ztool/models"
)

/**
获取流的详细信息
*/
func getStreamList(c *gin.Context) {

	//获取zlmediakit配置信息
	mediaConfig, _ := getMediaConfig()

	list, err := fetchStreamList(c, mediaConfig)
	if nil != err {
		c.JSON(http.StatusOK, common.RespError(err.Error()))
		return
	}

	r := common.RespData(list)
	c.JSON(http.StatusOK, r)
}

// closeStream 关闭zl流 /**
func closeStream(c *gin.Context) {

	//定义返回结构体
	var noReaderJson models.NoReaderJson

	if err := c.ShouldBind(&noReaderJson); err != nil {
		c.JSON(http.StatusOK, common.RespError(err.Error()))
		return
	}

	fmt.Println(&noReaderJson)

	go sendCloseStreamRequest(&noReaderJson)

	c.JSON(http.StatusOK, common.RespSuccess("操作成功"))
}

/**
获取当前在线媒体信息
*/ //定义一个数组
func getZLStreamList(stream string) ([]byte, error) {
	zlConfig := common.GetZLConfig()

	var urlBuild strings.Builder
	urlBuild.WriteString("http://")
	urlBuild.WriteString(zlConfig.Ip)
	urlBuild.WriteString(":")
	urlBuild.WriteString(strconv.Itoa(zlConfig.Port))
	urlBuild.WriteString("/index/api/getMediaList?secret=")
	//鉴权
	urlBuild.WriteString(zlConfig.Secret)

	if len(stream) != 0 {
		urlBuild.WriteString("&stream=")
		urlBuild.WriteString(stream)
	}

	url := urlBuild.String()

	resp, err := http.Get(url)
	if err != nil {
		return nil, err
	}

	defer resp.Body.Close()
	return ioutil.ReadAll(resp.Body)
}

/**
获取流的详细信息
*/
func fetchStreamList(c *gin.Context, mediaConfig *models.MediaServerConfig) (*[]models.StreamInfoWeb, error) {

	body, err := getZLStreamList("")

	if nil != err {
		return nil, err
	}

	//解析
	resp := models.StreamList{}

	if err := json.Unmarshal(body, &resp); nil != err {
		return nil, err
	}

	//判断执行结果
	if resp.Code != 0 {
		return nil, errors.New("获取流信息失败")
	}

	//解析流数据
	datas := resp.Data

	//创建一个新的切片
	var resultLists []models.StreamInfoWeb

	for i := range datas {
		stream := &datas[i]

		//统计rtmp即可
		if stream.Schema == "rtmp" {
			webStream := models.StreamInfoWeb{}
			//赋值基础信息
			webStream.StreamBaseInfo = stream.StreamBaseInfo

			//获取轨道信息
			tracks := stream.Tracks
			fecthTracks(&webStream, tracks)
			//获取播放地址
			fecthPreview(c, mediaConfig, &webStream, stream)
			resultLists = append(resultLists, webStream)
		}
	}

	return &resultLists, nil
}

// 根据stream（ID）查询流详细
func getStreamInfo(c *gin.Context) {
	path := c.Query("path")

	if path == "" {
		c.JSON(http.StatusOK, common.RespError("该流未打开"))
		return
	}

	//查询
	body, err := getZLStreamList(path)

	if nil != err {
		c.JSON(http.StatusOK, common.RespError(err.Error()))
		return
	}

	//解析
	resp := models.StreamList{}

	if err := json.Unmarshal(body, &resp); nil != err {
		c.JSON(http.StatusOK, common.RespError(err.Error()))
		return
	}

	fmt.Println(resp)

	//判断执行结果
	if resp.Code != 0 {
		c.JSON(http.StatusOK, common.RespError("获取流信息失败"))
		return
	}

	//获取zlmediakit配置信息
	mediaConfig, _ := getMediaConfig()

	//解析流数据
	datas := resp.Data
	var webStream *models.StreamInfoWeb

	for i := range datas {
		stream := &datas[i]

		//统计rtmp即可
		if stream.Schema == "rtmp" {
			s := models.StreamInfoWeb{}
			//赋值基础信息
			s.StreamBaseInfo = stream.StreamBaseInfo

			//获取轨道信息
			tracks := stream.Tracks
			fecthTracks(&s, tracks)
			//获取播放地址
			fecthPreview(c, mediaConfig, &s, stream)

			//只取第一个rtmp
			webStream = &s
			break
		}
	}

	if webStream == nil {
		c.JSON(http.StatusOK, common.RespError("获取流信息失败"))
		return
	}

	c.JSON(http.StatusOK, common.RespData(&webStream))
}

// 获取流音视频信息
func fecthTracks(webStream *models.StreamInfoWeb, tracks []models.StreamInfoTrack) {
	for ti := range tracks {
		track := &tracks[ti]
		switch track.CodecType {
		case 0:
			webStream.Video = *track
			break
		case 1:
			//音频
			webStream.Audio = *track
			break
		}
	}
}

//组合url地址
func fecthPreview(c *gin.Context, mediaConfig *models.MediaServerConfig, webStream *models.StreamInfoWeb, stream *models.StreamInfo) {

	streamPreview := models.StreamPreview{}

	zlConfig := common.GetZLConfig()

	ip, _, _ := net.SplitHostPort(c.Request.Host)

	proxyIp := zlConfig.ProxyIp

	//如果没有设置代理IP，则使用当前的IP
	if strings.TrimSpace(proxyIp) == "" {
		proxyIp = ip
	}

	//rtsp://somedomain.com/live/0
	//ws-flv  老版本zl
	//streamPreview.WSFlv = fmt.Sprintf("ws://%s:%d/%s/%s.flv", zlConfig.Ip, zlConfig.Port, stream.App, stream.Stream)
	//streamPreview.HTTPFlv = fmt.Sprintf("http://%s:%d/%s/%s.flv", zlConfig.Ip, zlConfig.Port, stream.App, stream.Stream)
	//ws-flv 新版本zl
	streamPreview.WSFlv = fmt.Sprintf("ws://%s:%d/%s/%s.live.flv", proxyIp, zlConfig.Port, stream.App, stream.Stream)
	streamPreview.HTTPFlv = fmt.Sprintf("http://%s:%d/%s/%s.live.flv", proxyIp, zlConfig.Port, stream.App, stream.Stream)
	streamPreview.Rtsp = fmt.Sprintf("rtsp://%s:%s/%s/%s", proxyIp, mediaConfig.Rtspport, stream.App, stream.Stream)
	streamPreview.Rtmp = fmt.Sprintf("rtmp://%s:%s/%s/%s", proxyIp, mediaConfig.Rtmpport, stream.App, stream.Stream)

	webStream.Preview = streamPreview
}

// mediaConfig 获取zlmedikait配置
func mediaConfig(c *gin.Context) {
	mediaConfig, err := getMediaConfig()
	if nil != err {
		c.JSON(http.StatusOK, common.RespError("获取信息失败"))
		return
	}

	c.JSON(http.StatusOK, common.RespData(&mediaConfig))
}

// loadStreamRouter 将路由组注册进去
func loadStreamRouter(r *gin.Engine) {
	//服务接口
	vapi := r.Group("/api")
	{
		//获取流列表
		vapi.Any("/getStreamList", getStreamList)
		vapi.GET("/getStreamInfo", getStreamInfo)
		//关闭一个流
		vapi.Any("/closeStream", closeStream)
		vapi.Any("/getServerConfig", mediaConfig)
	}
}
